package com.example.demo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import com.example.demo.common.constant.SystemConstants;
import com.example.demo.mapper.SysDeptMapper;
import com.example.demo.model.converter.SysDeptConverter;
import com.example.demo.model.core.PageVo;
import com.example.demo.model.entity.SysDept;
import com.example.demo.model.form.DeptForm;
import com.example.demo.model.query.DeptQuery;
import com.example.demo.model.vo.DeptVO;
import com.example.demo.model.vo.OptionVO;
import com.example.demo.service.SysDeptService;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class SysDeptServiceImpl implements SysDeptService {

    @Autowired
    private SysDeptConverter sysDeptConverter;
    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Override
    @CacheEvict(value = "deptOptions", key = "'deptOptions'")
    public void add(DeptForm form) {
        if (StrUtil.isBlank(form.getPid())) {
            form.setPid(SystemConstants.ROOT_NODE);
        }

        Assert.isTrue(sysDeptMapper.selectCountByQuery(QueryWrapper.create().eq("name", form.getName())) == 0, "部门名称已存在");

        SysDept entity = sysDeptConverter.toEntity(form);
        sysDeptMapper.insert(entity);
    }

    @Override
    @CacheEvict(value = "deptOptions", key = "'deptOptions'")
    public void update(DeptForm form) {
        Assert.isTrue(sysDeptMapper.selectCountByQuery(QueryWrapper.create().eq("name", form.getName()).ne("id", form.getId())) == 0, "部门名称已存在");

        SysDept entity = sysDeptConverter.toEntity(form);
        sysDeptMapper.update(entity);
    }

    @Override
    @CacheEvict(value = "deptOptions", key = "'deptOptions'")
    public void delete(List<String> ids) {
        sysDeptMapper.deleteBatchByIds(ids);
    }

    @Override
    public PageVo<DeptVO> page(DeptQuery query) {

        QueryWrapper wrapper = QueryWrapper.create();
        if (StrUtil.isNotBlank(query.getName())) {
            wrapper.like("name", query.getName());
        }
        if (StrUtil.isNotBlank(query.getPid())) {
            wrapper.eq("pid", query.getPid());
        }
        Page<SysDept> page = sysDeptMapper.paginate(query.getPageNum(), query.getPageSize(), wrapper);

        PageVo<SysDept> pageVo = new PageVo<>();
        pageVo.setList(page.getRecords());
        pageVo.setTotal(page.getTotalRow());
        return sysDeptConverter.toPageVo(pageVo);
    }

    @Override
    public DeptForm form(String id) {
        SysDept sysDepts = sysDeptMapper.selectOneById(id);
        Assert.notNull(sysDepts,"部门不存在");
        return sysDeptConverter.toForm(sysDepts);
    }

    @Override
    @Cacheable(value = "deptOptions", key = "'deptOptions'")
    public List<OptionVO<String>> options(DeptQuery query) {
        QueryWrapper wrapper = QueryWrapper.create().select("id", "name", "pid").orderBy("ordernum", false);
        List<SysDept> deptList = sysDeptMapper.selectListByQuery(wrapper);
        if (deptList.isEmpty()) {
            return List.of();
        }
        // sysDepts 转成树形结构，其中 pid 为 root 的为根节点，转换成List<OptionVo<String>>

        Set<String> deptIds = deptList.stream().map(SysDept::getId).collect(Collectors.toSet());

        Set<String> parentIds = deptList.stream().map(SysDept::getPid).collect(Collectors.toSet());

        List<String> rootIds = CollectionUtil.subtractToList(parentIds, deptIds);

        // 递归生成部门树形列表
        return rootIds.stream()
                .flatMap(rootId -> recurDeptTreeOptions(rootId, deptList).stream())
                .toList();
    }

    /**
     * 递归生成部门表格层级列表
     *
     * @param parentId 父ID
     * @param deptList 部门列表
     * @return 部门表格层级列表
     */
    public static List<OptionVO<String>> recurDeptTreeOptions(String parentId, List<SysDept> deptList) {
        return CollectionUtil.emptyIfNull(deptList).stream()
                .filter(dept -> dept.getPid().equals(parentId))
                .map(dept -> {
                    OptionVO<String> option = new OptionVO<>(dept.getId(), dept.getName());
                    List<OptionVO<String>> children = recurDeptTreeOptions(dept.getId(), deptList);
                    if (CollectionUtil.isNotEmpty(children)) {
                        option.setChildren(children);
                    }
                    return option;
                })
                .collect(Collectors.toList());
    }
}




